:- load "%%/meta/filters.sl" #

:- retract (import .f :- .c) #

import .f0 :-
	-- Checks if we are being nested
	getOrDefault IMPORTING .parent .,
	set IMPORTING .f0
	,
	addRelativePath .f0 .f1
	,
	if (not (IMPORTED .f1)) then (
		assert (IMPORTED .f1),
--		write "[INFO] Importing" .f1, nl,
		file.pathTail .f1 .path .,
		,
		addHomePath .f1 .f2,
		temporary .stream,
		stream.readFile .stream .f2,
		finally (
			readContent .stream .text
		) (
			stream.close .stream
		),
		parse .text .parsed,
		importCode .parsed
	)
	!
	-- Back to previous file
	bound .parent, set IMPORTING .parent
	;
	-- Predicate check; only when all imports complete
	checkUndefined, unset IMPORTING
	! #

addRelativePath .f0 .f1 :- -- Relative to current file
	not (char.at .f0 0 .c, (.c = "/"; .c = "%%")),
	get IMPORTING .importing !
	file.pathTail .importing .path .,
	concat .path .f0 .f1 #
addRelativePath .f .f #

addHomePath .f0 .f1 :- -- Import from singlog home
	char.at .f0 0 "%%" !
	substr .f0 1 0 .rel,
	home.dir .home,
	concat .home .rel .f1 #
addHomePath .f .f #

importCode $ #
importCode .code :-
	infix .code .clause "#" .remains,
	importRule .clause,
	importCode .remains #

importRule (:- .query) :- !
	.query #
importRule .r0 :-
	rule.headTail .r0 .q .c,
	filter.program (.q :- .c) (.q1 :- .c1),
	rule.headTail .r1 .q1 .c1,
	checkSingleton .r1,
	assert .r1 ! #
importRule .rule :-
	write "[FAILED] Cannot import:" .rule, nl, nl #

	-- Ignores first line if it is bash comment (as if Unix script)
readContent .s .text :-
	stream.line .s .line !
	readRemainingLines .s .remains,
	if (char.at .line 0 "#") then (
		.text = .remains
	) else (
		concat .line "%0A" .remains .text
	) #

readRemainingLines .s .text :-
	stream.line .s .line !
	readRemainingLines .s .remains,
	concat .line "%0A" .remains .text #
readRemainingLines . "" #

file.pathTail .file .path .tail :- rightSplit .file "/" .path .tail ! #
file.pathTail .file "" .file #

rightSplit .s .ch .left .right :-
	any .global (
		forall (char.at .s .i .ch) (set .global .i),
		get .global .pos
	),
	let .pos1 (.pos + 1),
	substr .s 0 .pos .left,
	substr .s .pos1 0 .right ! #
